#include "sal.h"
#include "dal.h"
#include "ctc_cli.h"
#include "usw/include/drv_enum.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"
#include "usw/include/drv_chip_ctrl.h"
#include "ctc_dkit.h"
#include "ctc_dkit_common.h"
#include "ctc_usw_dkit_misc.h"
#include "ctc_usw_dkit.h"
#include "common/duet2/ctc_dt2_dkit_serdes.h"
#include "common/tsingma/ctc_tm_dkit_serdes.h"
extern ctc_dkit_chip_api_t* g_dkit_chip_api[CTC_DKITS_MAX_LOCAL_CHIP_NUM];

#define MAX_PER_LINE                 512
#define CTC_DKIT_LINKLIST_MAX_OP_NUM 7

enum ctc_dkit_misc_integrity_op_e
{
    CTC_DKIT_MISC_INTEGRITY_OP_NONE,
    CTC_DKIT_MISC_INTEGRITY_OP_E,
    CTC_DKIT_MISC_INTEGRITY_OP_BE,
    CTC_DKIT_MISC_INTEGRITY_OP_LE,
    CTC_DKIT_MISC_INTEGRITY_OP_B,
    CTC_DKIT_MISC_INTEGRITY_OP_L,
    CTC_DKIT_MISC_INTEGRITY_OP_NUM
};
typedef enum ctc_dkit_misc_integrity_op_e ctc_dkit_misc_integrity_op_t;

enum ctc_dkit_misc_integrity_check_e
{
    CTC_DKIT_MISC_INTEGRITY_CHECK_NONE,
    CTC_DKIT_MISC_INTEGRITY_CHECK_STATUS,
    CTC_DKIT_MISC_INTEGRITY_CHECK_LINKLIST,
    CTC_DKIT_MISC_INTEGRITY_CHECK_INTR,
    CTC_DKIT_MISC_INTEGRITY_CHECK_NUM
};
typedef enum ctc_dkit_misc_integrity_check_e ctc_dkit_misc_integrity_check_t;
static uint32 bit_map[1024];
#define __SERDES__

uint16 dkit_serdes_mapping(uint8 lchip, uint16 serdes_id)
{
    uint16 mapping_serdes_id = serdes_id;

    if(((DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip)) || (DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip))) && DRV_IS_TSINGMA(lchip))
    {
        if((serdes_id >= 16) && (serdes_id <= 19))
        {
            mapping_serdes_id = serdes_id + 4;
        }
        else if((serdes_id >= 20) && (serdes_id <= 23))
        {
            mapping_serdes_id = serdes_id - 4;
        }
    }

    return mapping_serdes_id;
}

int32
ctc_usw_dkit_misc_read_serdes(void* para)
{
    ctc_dkit_serdes_wr_t* p_para = (ctc_dkit_serdes_wr_t*)para;
    int32 ret = 0;
    if(g_dkit_chip_api[p_para->lchip]->dkits_read_serdes)
    {
        p_para->serdes_id = dkit_serdes_mapping(p_para->lchip, p_para->serdes_id);
        ret = g_dkit_chip_api[p_para->lchip]->dkits_read_serdes(para);
        p_para->serdes_id = dkit_serdes_mapping(p_para->lchip, p_para->serdes_id);
    }

    return ret;
}


int32
ctc_usw_dkit_misc_write_serdes(void* para)
{
    ctc_dkit_serdes_wr_t* p_para = (ctc_dkit_serdes_wr_t*)para;
    int32 ret = 0;
    if(g_dkit_chip_api[p_para->lchip]->dkits_write_serdes)
    {
        p_para->serdes_id = dkit_serdes_mapping(p_para->lchip, p_para->serdes_id);
        ret = g_dkit_chip_api[p_para->lchip]->dkits_write_serdes(para);
        p_para->serdes_id = dkit_serdes_mapping(p_para->lchip, p_para->serdes_id);
    }

    return ret;
}


int32
ctc_usw_dkit_misc_read_serdes_aec_aet(void* para)
{
    ctc_dkit_serdes_wr_t* p_para = (ctc_dkit_serdes_wr_t*)para;
    int32 ret = 0;
    if(g_dkit_chip_api[p_para->lchip]->dkits_read_serdes_aec_aet)
    {
        ret = g_dkit_chip_api[p_para->lchip]->dkits_read_serdes_aec_aet(para);
    }

    return ret;
}

int32
ctc_usw_dkit_misc_write_serdes_aec_aet(void* para)
{
    ctc_dkit_serdes_wr_t* p_para = (ctc_dkit_serdes_wr_t*)para;
    int32 ret = 0;
    if(g_dkit_chip_api[p_para->lchip]->dkits_write_serdes_aec_aet)
    {
        ret = g_dkit_chip_api[p_para->lchip]->dkits_write_serdes_aec_aet(para);
    }

    return ret;
}


int32
ctc_usw_dkit_misc_serdes_resert(uint8 lchip, uint16 serdes_id)
{
    int32 ret = 0;
    if(g_dkit_chip_api[lchip]->dkits_serdes_resert)
    {
        serdes_id = dkit_serdes_mapping(lchip, serdes_id);
        ret = g_dkit_chip_api[lchip]->dkits_serdes_resert(lchip, serdes_id);
        serdes_id = dkit_serdes_mapping(lchip, serdes_id);
    }

    return ret;
}


int32
ctc_usw_dkit_misc_serdes_status(uint8 lchip, uint16 serdes_id, uint32 type, char* file_name)
{
    int32 ret = 0;
    if(g_dkit_chip_api[lchip]->dkits_dump_serdes_status)
    {

        serdes_id= dkit_serdes_mapping(lchip, serdes_id);
        ret = g_dkit_chip_api[lchip]->dkits_dump_serdes_status(lchip, serdes_id, type, file_name);
        serdes_id= dkit_serdes_mapping(lchip, serdes_id);
    }

    return ret;
}

int32
ctc_usw_dkit_misc_serdes_ctl(void* p_para)
{
    ctc_dkit_serdes_ctl_para_t* p_serdes_para = (ctc_dkit_serdes_ctl_para_t*)p_para;
    int32 ret = 0;
    if(g_dkit_chip_api[p_serdes_para->lchip]->dkits_serdes_ctl)
    {
        p_serdes_para->serdes_id = dkit_serdes_mapping(p_serdes_para->lchip, p_serdes_para->serdes_id);
        ret = g_dkit_chip_api[p_serdes_para->lchip]->dkits_serdes_ctl(p_para);
        p_serdes_para->serdes_id = dkit_serdes_mapping(p_serdes_para->lchip, p_serdes_para->serdes_id);
    }

    return ret;
}

#define __Integrity_check___


#define MAX_PER_LINE                 512
#define OP_NONE         0
#define OP_E            1
#define OP_BE           2
#define OP_LE           3
#define OP_B            4
#define OP_L            5
static uint32 bit_map[1024];
int32 _ctc_usw_dkit_misc_read_entry(uint8 chip_id, tbls_id_t id, uint32 index, uint32 offset, uint32*value)
{
    //uint8 chipid_base  = 0;
    uint32 hw_addr_base = 0;
    uint32 entry_size   = 0;
    uint32 max_entry    = 0;
    uint32 hw_addr_offset      = 0;
    int32  ret = 0;
    uint16 addr_offset = 0;

    if (MaxTblId_t <= id)
    {
        CTC_DKIT_PRINT("\nERROR! INVALID tbl/RegID! tbl/RegID: %d, file:%s line:%d function:%s\n",
                    id,__FILE__,__LINE__,__FUNCTION__);
        return CLI_ERROR;
    }

    DRV_IF_ERROR_RETURN(drv_usw_get_tbl_index_base(chip_id, id, index, &addr_offset));
    entry_size      = TABLE_ENTRY_SIZE(chip_id, id);
    max_entry       = TABLE_MAX_INDEX(chip_id, id);
    hw_addr_base    = TABLE_DATA_BASE(chip_id,id,addr_offset);

    if ((index&0xFFFFFF) >= max_entry)
    {
        return CLI_ERROR;
    }
    /*TODO: dynamic table*/
    if ((4 == entry_size) || (8 == entry_size))
    {/*1w or 2w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * entry_size + offset;
    }
    else if (entry_size <= 4*4)
    {/*4w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * 4*4 + offset;
    }
    else if (entry_size <= 4*8)
    {/*8w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * 4*8 + offset;
    }
    /*
    else if (entry_size <= 4*12)
    {//12w
        hw_addr_offset  =   hw_addr_base + index * 4*12 + offset;
    }
    */
    else if (entry_size <= 4*16)
    {/*16w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * 4*16 + offset;
    }
    /*
    else if (entry_size <= 4*20)
    {//20w
        hw_addr_offset  =   hw_addr_base + index * 4*20 + offset;
    }
    else if (entry_size <= 4*24)
    {//24w
        hw_addr_offset  =   hw_addr_base + index * 4*24 + offset;
    }
    else if (entry_size <= 4*28)
    {//28w/
        hw_addr_offset  =   hw_addr_base + index * 4*28 + offset;
    }
    */
    else if (entry_size <= 4*32)
    {/*32w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * 4*32 + offset;
    }
    /*
    else if (entry_size <= 4*36)
    {//36w
        hw_addr_offset  =   hw_addr_base + index * 4*36 + offset;
    }
    else if (entry_size <= 4*40)
    {//40w/
        hw_addr_offset  =   hw_addr_base + index * 4*40 + offset;
    }
    */
    else if (entry_size <= 4*64)
    {/*64w*/
        hw_addr_offset  =   hw_addr_base + (index&0xFFFFFF) * 4*64 + offset;
    }

    //ret = drv_get_chipid_base(&chipid_base);

    //if (ret < DRV_E_NONE)
    //{
    //    ctc_cli_out("Get chipId base ERROR! Value = 0x%08x\n", chipid_base);
    //    return ret;
    //}

    ret = drv_usw_chip_read(chip_id, hw_addr_offset, value);

    if (ret < DRV_E_NONE)
    {
        CTC_DKIT_PRINT("0x%08x address read ERROR!\n", hw_addr_offset);
        return ret;
    }

    return CLI_SUCCESS;

}

static int32
_ctc_usw_dkit_misc_calc_inter_mask(uint8 chip_id, char *poly_str, uint32 *cal_val)
{
    uint32 value[2] = {0};
    char op_code = 0;
    char tbl_str[64] = {0};

    char* op_str = NULL;
    char* head = NULL;
    tbls_id_t tbl_id = 0;
    uint32 result = 0;
    uint32 offset = 0;
    uint32 index  = 0;
    int32 ret = 0;

    DRV_PTR_VALID_CHECK(poly_str);
    head = sal_strstr(poly_str, "[");
    if (NULL != head)
    {
        sal_sscanf(head, "[%[^.].%d.%d]", tbl_str, &index, &offset);

        if (DRV_E_NONE != drv_usw_get_tbl_id_by_string(chip_id, &tbl_id, tbl_str))
        {
            CTC_DKIT_PRINT("can't find tbl %s \n", tbl_str);
            return DRV_E_INVALID_TBL;
        }

        ret = _ctc_usw_dkit_misc_read_entry(chip_id, tbl_id, index, offset, &value[0]);
        if (DRV_E_NONE != ret)
        {
            CTC_DKIT_PRINT("read tbl_str %s index %d offset %d error\n", tbl_str, index, offset);
            return ret;
        }
        //DRV_IF_ERROR_RETURN(read_entry(chip_id, tbl_id, index, offset, &value[0]));

        op_str = sal_strstr(head, "{op ");
        if (NULL != op_str)
        {
            op_code = op_str[4];
            head = sal_strstr(op_str, "[");
            if(head)
            {
                sal_sscanf(head, "[0x%x]", &value[1]);
            }
        }
        result = value[0];
        switch (op_code)
        {
            case '+':
                result += value[1];
                break;
            case '-':
                result -= value[1];
                break;
            case '&':
                result &= value[1];
                break;
            case '|':
                result |= value[1];
                break;
            default:
                break;
        }
        *cal_val = result;
    }
    return DRV_E_NONE;
}

static int32
_ctc_usw_dkit_misc_get_id_by_poly(uint8 chip_id, char *poly_str, tbls_id_t* tbl_id, fld_id_t* fld_id)
{
    char tbl_str[64] = {0};
    char fld_str[64] = {0};
    char *head = NULL;

    head = sal_strstr(poly_str, "[");

    if (NULL == head)
    {
        return DRV_E_INVALID_PARAMETER;
    }
    else
    {
        sal_sscanf(head, "\x5b%[^.].%[^\x5d]", tbl_str, fld_str);
        if (DRV_E_NONE != drv_usw_get_tbl_id_by_string(chip_id, tbl_id, tbl_str))
        {
            CTC_DKIT_PRINT("can find table %s\n", tbl_str);
            return DRV_E_INVALID_TBL;
        }
        if (DRV_E_NONE != drv_usw_get_field_id_by_string(chip_id, *tbl_id, fld_id, fld_str))
        {
            CTC_DKIT_PRINT("can find field %s\n", fld_str);
            return DRV_E_INVALID_FLD;
        }
    }
    return DRV_E_NONE;
}


static int32
_ctc_usw_dkit_misc_calc_poly(uint8 lchip, uint32 index ,uint8 b_exted, uint8 mode,char *poly_str, char *result_str)
{
    #define MAX_OP_NUM 7
    uint8 op_time = 0;

    uint32 value[MAX_OP_NUM+1][4];
    char op_code[MAX_OP_NUM] = {0};
    char tbl_str[64] = {0};
    char fld_str[64] = {0};
    char tmp_fld_str[64] = {0};

    char* op_str = NULL;
    char *head = NULL;

    tbls_id_t tbl_id = 0;
    fld_id_t fld_id = 0;

    uint32 cmd = 0;
    uint32 result = 0;
    uint32 cnt = 0, dot_cnt = 0, s = 0;
    uint64 poly_idx = 0;
	uint32 ins_idx = 0;
	uint8 core_id =0;
	uint8 pp_id =0;
	uint8 dp_id =0;
	uint8 addr_ext_field =0;
	

    char *bit_split = NULL;
    uint32 start_bit = 0, end_bit = 0;

    //uint32 self_op_mult = 0;
    //uint32 self_op_value = 0;

    sal_memset(value, 0, sizeof(value));

    DRV_PTR_VALID_CHECK(poly_str);
    head = sal_strstr(poly_str, "[");
    if (NULL == head)
    {
        sal_sscanf(poly_str, "%d", &result);
        return result;
    }
    else
    {
        while ((op_str = sal_strstr(head, "{op ")))
        {
            op_code[op_time] = op_str[4];
            //DbgTool_DBG_INFO("debug op_code[%d]:%c\n",op_time, op_code[op_time]);

            #if 0
            if (op_code[op_time] == '*')
            {
                sal_sscanf(op_str,"{op * %d}",&self_op_value);
                self_op_mult = 1;
                head = sal_strstr(op_str+1, "{op ");
                continue;
            }
            #endif
            if (b_exted)
            {
                dot_cnt = 0;
                for (s = 0; s < strlen(head); s++)
                {
                    if (head[s] == '.')
                    {
                        dot_cnt++;
                    }
                }
                if (dot_cnt == 3)
                {
                #ifdef PHYS_ADDR_IS_64BIT
                    sal_sscanf(head, "\x5b%[^.].%d.%lx.%[^\x5d]", tbl_str, &ins_idx, &poly_idx, fld_str);
				#else
				    sal_sscanf(head, "\x5b%[^.].%d.%llx.%[^\x5d]", tbl_str, &ins_idx, &poly_idx, fld_str);
				#endif
                    poly_idx = (ins_idx<<24) | poly_idx;
                }
                else
                {
                #ifdef PHYS_ADDR_IS_64BIT
				sal_sscanf(head, "\x5b%[^.].%lx.%[^\x5d]", tbl_str, &poly_idx, fld_str);
				#else
				    sal_sscanf(head, "\x5b%[^.].%llx.%[^\x5d]", tbl_str, &poly_idx, fld_str);
				#endif
                }
            }
            else
            {
                sal_sscanf(head, "\x5b%[^.].%[^\x5d]", tbl_str, fld_str);
                poly_idx = index;
            }
			addr_ext_field = (poly_idx >> 32)&0xFF;
			core_id = (((addr_ext_field >> 6)&0x3) == 2)? 1 : 0;
			pp_id = ((addr_ext_field >> 2)&0xF);
			pp_id = (pp_id == 8)? 3 : (pp_id == 4)? 2 : (pp_id == 2)? 1 : 0; 
			dp_id = ((addr_ext_field&0x3) == 2)? 1 : 0;


            //DbgTool_DBG_INFO("op,tbl_str:%s,fld_str:%s\n",tbl_str,fld_str);

            if (mode)
            {
                if (DRV_E_NONE != drv_usw_get_tbl_id_by_string(lchip, &tbl_id, tbl_str))
                {
                    CTC_DKIT_PRINT("can't find tbl %s \n", tbl_str);
                    return DRV_E_INVALID_TBL;
                }

                if (DRV_E_NONE != drv_usw_get_field_id_by_string(lchip, tbl_id, &fld_id, fld_str))
                {
                    if (((DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip) || DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip)) && 1 == core_id) ||
                        (((DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip) || DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip)) && 3 == pp_id)))
                    {
                        continue;
                    }

                    cmd = DRV_IOR(tbl_id, fld_id);
                    if (DRV_E_NONE != DRV_FIELD_IOCTL(lchip+core_id*PP_NUM_PER_CORE+pp_id, (uint32)(poly_idx&0xFFFFFFFF), DRV_CMD_DP_EN(cmd,dp_id), value[op_time]))
                    {
                        CTC_DKIT_PRINT("read tbl_str %s fld_str %s error\n", tbl_str, fld_str);
                    }
                    #if 0
                    if (self_op_mult)
                    {
                        value[op_time] = value[op_time] * self_op_value;
                        self_op_mult = 0;
                    }
                    #endif
                    }
            }
            if (result_str)
            {
            #ifdef PHYS_ADDR_IS_64BIT
                sal_sprintf(result_str + sal_strlen(result_str), "[%s.%lx.%s] {op %c} " ,tbl_str, poly_idx, fld_str, op_code[op_time]);
			#else
			    sal_sprintf(result_str + sal_strlen(result_str), "[%s.%llx.%s] {op %c} " ,tbl_str, poly_idx, fld_str, op_code[op_time]);
			#endif
            }

            head = sal_strstr(op_str, "[");
            if(NULL == head)
            {
                break;
            }
            sal_memset(tbl_str, 0, sizeof(tbl_str));
            sal_memset(fld_str, 0, sizeof(fld_str));
            op_str = NULL;
            op_time ++;
            if (op_time > MAX_OP_NUM)
            {

            }

        }

        if (NULL == head)
        {
            sal_sscanf(poly_str, "%d", &result);
            return result;
        }   
        if (b_exted)
        {
            dot_cnt = 0;
            for (s = 0; s < strlen(head); s++)
            {
                if (head[s] == '.')
                {
                    dot_cnt++;
                }
            }
            if (dot_cnt == 3)
            {
            #ifdef PHYS_ADDR_IS_64BIT
                sal_sscanf(head, "\x5b%[^.].%d.%lx.%[^\x5d]", tbl_str, &ins_idx, &poly_idx, fld_str);
            #else
                sal_sscanf(head, "\x5b%[^.].%d.%llx.%[^\x5d]", tbl_str, &ins_idx, &poly_idx, fld_str);
            #endif
                poly_idx = (ins_idx << 24) | poly_idx;
            }
            else
            {
            #ifdef PHYS_ADDR_IS_64BIT
                sal_sscanf(head, "\x5b%[^.].%lx.%[^\x5d]", tbl_str, &poly_idx, fld_str);
            #else
                sal_sscanf(head, "\x5b%[^.].%llx.%[^\x5d]", tbl_str, &poly_idx, fld_str);
            #endif
            }
        }
        else
        {
            sal_sscanf(head, "\x5b%[^.].%[^\x5d]", tbl_str, fld_str);
            poly_idx = index;
        }
        addr_ext_field = (poly_idx >> 32)&0xFF;
        core_id = (((addr_ext_field >> 6)&0x3) == 2)? 1 : 0;
        pp_id = ((addr_ext_field >> 2)&0xF);
        pp_id = (pp_id == 8)? 3 : (pp_id == 4)? 2 : (pp_id == 2)? 1 : 0; 
        dp_id = ((addr_ext_field&0x3) == 2)? 1 : 0;

        //DbgTool_DBG_INFO("b_exted:%d,tbl_str:%s,fld_str:%s\n",b_exted,tbl_str,fld_str);

        //process such as (31:0), (63:32) kind of field, bits larger than 32
        bit_split = sal_strstr(fld_str, "(");
        if(bit_split)
        {
            sal_strcpy(tmp_fld_str,fld_str);
            sal_sscanf(tmp_fld_str, "%[^\x28]\x28%d:%d\x29", fld_str, &end_bit, &start_bit);
        }

        if (mode)
        {
            if ( DRV_E_NONE != drv_usw_get_tbl_id_by_string(lchip, &tbl_id, tbl_str))
            {
                CTC_DKIT_PRINT("can't find tbl %s \n", tbl_str);
                return DRV_E_INVALID_TBL;
            }

            if (DRV_E_NONE != drv_usw_get_field_id_by_string(lchip, tbl_id, &fld_id, fld_str))
            {
                CTC_DKIT_PRINT("can find field %s\n", fld_str);
                return DRV_E_INVALID_FLD;
            }

            if (((DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip) || DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip)) && 1 == core_id) ||
                (((DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip) || DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip)) && 3 == pp_id)))
            {
                return DRV_E_NONE;
            }

            cmd = DRV_IOR(tbl_id, fld_id);
            if (DRV_E_NONE != DRV_FIELD_IOCTL(lchip+core_id*PP_NUM_PER_CORE+pp_id, (uint32)(poly_idx&0xFFFFFFFF), DRV_CMD_DP_EN(cmd,dp_id), value[op_time]))
            {
                CTC_DKIT_PRINT("read tbl_str %s fld_str %s error\n", tbl_str, fld_str);
            }
            #if 0
            if (self_op_mult)
            {
                value[op_time] = value[op_time] * self_op_value;
            }
            #endif
        }
        if (result_str)
        {
        #ifdef PHYS_ADDR_IS_64BIT
		    sal_sprintf(result_str + sal_strlen(result_str), "[%s.%lx.%s] " ,tbl_str, poly_idx, fld_str);
		#else
            sal_sprintf(result_str + sal_strlen(result_str), "[%s.%llx.%s] " ,tbl_str, poly_idx, fld_str);
		#endif
		}

        cnt    = 0;

        //process such as (31:0), (63:32) kind of field, bits larger than 32
        if (bit_split)
        {
            if(start_bit == 0 && end_bit == 31)
            {
                result = value[cnt][0];
            }
            else if (start_bit == 32 && end_bit == 63)
            {
                result = value[cnt][1];
            }
            else if (start_bit == 64 && end_bit == 95)
            {
                result = value[cnt][2];
            }
            else if (start_bit == 96 && end_bit == 127)
            {
                result = value[cnt][3];
            }
            else
            {
                CTC_DKIT_PRINT("Unsupported bit split\n");
            }

        }
        else
        {
            result = value[cnt][0];
        }

        //DbgTool_DBG_INFO("value[%d]:%d\n",cnt,value[cnt][0]);

        while (cnt < op_time)
        {
            switch (op_code[cnt])
            {
                case '+':
                    result += value[cnt+1][0];
                    break;
                case '-':
                    result -= value[cnt+1][0];
                    break;
                case '&':
                    result &= value[cnt+1][0];
                    break;
                case '|':
                    result |= value[cnt+1][0];
                    break;
                default:
                    break;
            }
            cnt++;
        }
    }
    return result;
}



static int32
_ctc_usw_dkit_misc_integrity_result_do(uint8 chip_id, char *line, char *result, uint8 *check_pass)
{
#define CHECK_NONE      0
#define CHECK_STATUS    1
#define CHECK_LINK_LIST 2
#define CHECK_INTR      3

    uint8 op_code = OP_NONE;

    char* poly_str = NULL;
    char* poly_str_right = NULL;

    int32 exp_val = 0;
    int32 rel_val = 0;

    uint32 counter  = 0;
    uint32 index    = 0;
    uint32 next_index = 0;

    uint32 tbl_id = 0;
    fld_id_t fld_id = 0;
    uint32 cmd = 0;

    static uint8 integrity_stat = CHECK_NONE;
    static uint32 exp_head = 0;
    static uint32 exp_tail = 0;
    static uint32 exp_cnt = 0;

    poly_str = mem_malloc(MEM_CLI_MODULE, MAX_PER_LINE*sizeof(char));
    if (NULL == poly_str)
    { 
        return CLI_ERROR;
    }
    poly_str_right = mem_malloc(MEM_CLI_MODULE, MAX_PER_LINE*sizeof(char));
    if (NULL == poly_str_right)
    { 
        mem_free(poly_str);
        return CLI_ERROR;
    }
    sal_memset(poly_str, 0, MAX_PER_LINE*sizeof(char));
    sal_memset(poly_str_right, 0, MAX_PER_LINE*sizeof(char));
    if (('\r' == line[0]) && ('\n' == line[1]))
    {
        sal_strncpy(result, line, MAX_PER_LINE);
    }
    else if ('#' == line[0])
    {
        if (sal_strstr(line, "Status Check"))
        {
            integrity_stat = CHECK_STATUS;
        }
        else if (sal_strstr(line, "Link List Check Begin"))
        {
            integrity_stat = CHECK_LINK_LIST;
            sal_memset(bit_map, 0, sizeof(bit_map));
        }
        else if (sal_strstr(line, "Link List Check End"))
        {
            integrity_stat = CHECK_NONE;
        }
        else if (sal_strstr(line, "Interrupt Check"))
        {
            integrity_stat = CHECK_INTR;
        }

        sal_strncpy(result, line, MAX_PER_LINE);
    }
    else
    {
        /*get op code*/
        if (sal_strstr(line, ">="))
        {
            op_code = OP_BE;
        }
        else if (sal_strstr(line, "<="))
        {
            op_code = OP_LE;
        }
        else if (sal_strstr(line, ">"))
        {
            op_code = OP_B;
        }
        else if (sal_strstr(line, "<"))
        {
            op_code = OP_L;
        }
        else if (sal_strstr(line, "="))
        {
            op_code = OP_E;
        }
        else
        {
            op_code = OP_NONE;
        }

        /*to calc poly*/
        if (OP_NONE == op_code)
        {
            sal_strncpy(result, line, MAX_PER_LINE);
        }
        else
        {
            /*status check*/
            if (CHECK_STATUS == integrity_stat)
            {
                switch (op_code)
                {
                    case OP_E:
                        sal_sscanf(line, "%[^=]=%s", poly_str, poly_str_right);
                        rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                        exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                        if (rel_val != exp_val)
                        {
                            CTC_DKIT_PRINT("%s = %d@%d\n", poly_str, rel_val, exp_val);
                            sal_sprintf(result, "%s = %d@%d\n", poly_str, rel_val, exp_val);
                            *check_pass = FALSE;
                        }
                        break;
                    case OP_BE:
                        sal_sscanf(line, "%[^>=]>=%s", poly_str, poly_str_right);
                        rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                        exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                        if (rel_val < exp_val)
                        {
                            CTC_DKIT_PRINT("%s >= %d@%d\n", poly_str, rel_val, exp_val);
                            sal_sprintf(result, "%s >= %d@%d\n", poly_str, rel_val, exp_val);
                            *check_pass = FALSE;
                        }
                        break;
                    case OP_LE:
                        sal_sscanf(line, "%[^<=]<=%s", poly_str, poly_str_right);
                        rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                        exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                        if (rel_val > exp_val)
                        {
                            CTC_DKIT_PRINT("%s <= %d@%d\n", poly_str, rel_val, exp_val);
                            sal_sprintf(result, "%s >= %d@%d\n", poly_str, rel_val, exp_val);
                            *check_pass = FALSE;
                        }
                        break;
                    case OP_B:
                        sal_sscanf(line, "%[^>]>%s", poly_str, poly_str_right);
                        rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                        exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                        if (rel_val <= exp_val)
                        {
                            CTC_DKIT_PRINT("%s > %d@%d\n", poly_str, rel_val, exp_val);
                            sal_sprintf(result, "%s >= %d@%d\n", poly_str, rel_val, exp_val);
                            *check_pass = FALSE;
                        }
                        break;
                    default:/*case OP_L:*/
                        sal_sscanf(line, "%[^<]<%s", poly_str, poly_str_right);
                        rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                        exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                        if (rel_val >= exp_val)
                        {
                            CTC_DKIT_PRINT("%s < %d@%d\n", poly_str, rel_val, exp_val);
                            sal_sprintf(result, "%s >= %d@%d\n", poly_str, rel_val, exp_val);
                            *check_pass = FALSE;
                        }
                        break;
                }

            }
            /*link list check*/
            else if (CHECK_LINK_LIST == integrity_stat)
            {
                if (sal_strstr(line, "{var"))
                {
                    sal_sscanf(line, "%*[^=]=%s", poly_str);
                }
                else
                {

                }

                if (sal_strstr(line, "{var linkHeadPtr}"))
                {
                    exp_head = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, FALSE, 1,poly_str, NULL);
                }
                else if (sal_strstr(line, "{var linkTailPtr}"))
                {
                    exp_tail = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, FALSE, 1,poly_str, NULL);
                }
                else if (sal_strstr(line, "{var linkCnt}"))
                {
                    exp_cnt = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, FALSE, 1,poly_str, NULL);
                }
                else if (sal_strstr(line, "{var nextPtr}"))
                {
                    counter   = 0;
                    index     = exp_head;
                    /*get tbl & field id*/
                    _ctc_usw_dkit_misc_get_id_by_poly(chip_id, poly_str, &tbl_id, &fld_id);

                    for (;;)
                    {
                        if (DKITS_IS_BIT_SET(bit_map[index / 32], (index % 32)))
                        {
				  CTC_DKIT_PRINT("@index (0x%x) looped\n", index);
                            break;
                        }
                        else
                        {
                            DKITS_BIT_SET(bit_map[index / 32], (index % 32));
                        }
                        counter ++;
                        if ((index == exp_tail) || (counter == exp_cnt))
                        {
                            //kal_printf("index %d, exp_tail %d\n", index, exp_tail);
                            //kal_printf("counter %d, exp_cnt %d\n", counter, exp_cnt);
                            break;
                        }

                        cmd = DRV_IOR(tbl_id, fld_id);
                        DRV_FIELD_IOCTL(chip_id, index, cmd, &next_index);
                        if (next_index >= TABLE_MAX_INDEX(chip_id, tbl_id))
                        {
			         CTC_DKIT_PRINT("@index 0x%x Next Idx is 0x%x\n", index, next_index);
                            break;
                        }
                        index = next_index;

                    }

                    if (next_index != exp_tail)
                    {
                        CTC_DKIT_PRINT("@actual tail = 0x%x, expetc tail = 0x%x\n", next_index, exp_tail);
                        sal_sprintf(result, "@actual tail = 0x%x, expetc tail = 0x%x\n", next_index, exp_tail);
                        *check_pass = FALSE;
                    }
                    else if (counter != exp_cnt)
                    {
                        CTC_DKIT_PRINT("@actual counter = 0x%x, expetc counter = 0x%x\n", counter, exp_cnt);
                        sal_sprintf(result, "@actual counter = 0x%x, expetc counter = 0x%x\n", counter, exp_cnt);
                        *check_pass = FALSE;
                    }
                }
                else
                {
                    switch (op_code)
                    {
                        case OP_E:
                            sal_sscanf(line, "%[^=]=%s", poly_str, poly_str_right);
                            rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                            exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                            if (rel_val != exp_val)
                            {
                                CTC_DKIT_PRINT("%s = %d@%d\n", poly_str, rel_val, exp_val);
                                sal_sprintf(result, "%s = %d@%d\n", poly_str, rel_val, exp_val);
                                *check_pass = FALSE;
                            }
                            break;
                        case OP_BE:
                            sal_sscanf(line, "%[^>=]>=%s", poly_str, poly_str_right);
                            rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                            exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                            if (rel_val < exp_val)
                            {
                                CTC_DKIT_PRINT("%s >= %d@%d\n", poly_str, rel_val, exp_val);
                                sal_sprintf(result, "%s >= %d@%d\n", poly_str, rel_val, exp_val);
                                *check_pass = FALSE;
                            }
                            break;
                        case OP_LE:
                            sal_sscanf(line, "%[^<=]<=%s", poly_str, poly_str_right);
                            rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                            exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                            if (rel_val > exp_val)
                            {
                                CTC_DKIT_PRINT("%s <= %d@%d\n", poly_str, rel_val, exp_val);
                                sal_sprintf(result, "%s <= %d@%d\n", poly_str, rel_val, exp_val);
                                *check_pass = FALSE;
                            }
                            break;
                        case OP_B:
                            sal_sscanf(line, "%[^>]>%s", poly_str, poly_str_right);
                            rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                            exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                            if (rel_val <= exp_val)
                            {
                                CTC_DKIT_PRINT("%s > %d@%d\n", poly_str, rel_val, exp_val);
                                sal_sprintf(result, "%s > %d@%d\n", poly_str, rel_val, exp_val);
                                *check_pass = FALSE;
                            }
                            break;
                        default:/*case OP_L:*/
                            sal_sscanf(line, "%[^<]<%s", poly_str, poly_str_right);
                            rel_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str, NULL);
                            exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, TRUE, 1,poly_str_right, NULL);
                            if (rel_val >= exp_val)
                            {
                                CTC_DKIT_PRINT("%s < %d@%d\n", poly_str, rel_val, exp_val);
                                sal_sprintf(result, "%s < %d@%d\n", poly_str, rel_val, exp_val);
                                *check_pass = FALSE;
                            }
                            break;
                    }
                }
            }
            /*interrupt check*/
            else if (CHECK_INTR == integrity_stat)
            {
                uint32 val = 0;

                sal_sscanf(line, "%[^=]=%s", poly_str, poly_str_right);
                rel_val = _ctc_usw_dkit_misc_calc_inter_mask(chip_id, poly_str, &val);
                exp_val = _ctc_usw_dkit_misc_calc_poly(chip_id, 0, FALSE, 1,poly_str_right, NULL);
                if (val != exp_val)
                {
                    CTC_DKIT_PRINT("%s = %u@%d\n", poly_str, val, exp_val);
                    sal_sprintf(result, "%s = %u@%d\n", poly_str, val, exp_val);
                    *check_pass = FALSE;
                }
            }
            /*none check*/
            else
            {
                exp_head = 0;
                exp_tail = 0;
                exp_cnt  = 0;
            }
        }

    }
    if ( poly_str_right)
    {
        mem_free(poly_str_right);
    }
    if (poly_str)
    {
        mem_free(poly_str);
    }
    return DRV_E_NONE;
}




int32
ctc_usw_dkit_misc_integrity_check(uint8 chip_id, void* p_para1, void* p_para2, void* p_para3)
{
    sal_file_t  gold_fp = NULL;
    sal_file_t  rslt_fp = NULL;
    char* line     = NULL;
    char* result   = NULL;
    uint8 check_pass = TRUE;
    int32 ret = DRV_E_NONE;
    char*  gold_file = NULL;
    char*  rlt_file = NULL;

    DRV_PTR_VALID_CHECK(p_para1);
    DRV_PTR_VALID_CHECK(p_para2);
    DRV_PTR_VALID_CHECK(p_para3);
	
    gold_file = (char*)p_para1;
    rlt_file = (char*)p_para2;
	
    gold_fp = sal_fopen(gold_file, "r");
    if (NULL == gold_fp)
    {
        CTC_DKIT_PRINT("open golden file %s failed!\n", gold_file);
        return DRV_E_FILE_OPEN_FAILED;
    }

    rslt_fp = sal_fopen(rlt_file, "w+");
    if (NULL == rslt_fp)
    {
        sal_fclose(gold_fp);
        rslt_fp = NULL;
        CTC_DKIT_PRINT("open destination file %s failed!\n", rlt_file);
        return DRV_E_FILE_OPEN_FAILED;
    }
    line = mem_malloc(MEM_CLI_MODULE, MAX_PER_LINE*sizeof(char));
    if (NULL == line)
    {
        ret = CLI_ERROR;
        goto error1;
    }
    sal_memset(line, 0, MAX_PER_LINE*sizeof(char));
    result = mem_malloc(MEM_CLI_MODULE, MAX_PER_LINE*sizeof(char));
    if (NULL == result)
    {
        ret = CLI_ERROR;
        goto error1;
    }
    sal_memset(result, 0, MAX_PER_LINE*sizeof(char));
    
    while (NULL != sal_fgets(line, MAX_PER_LINE, gold_fp))
    {
        _ctc_usw_dkit_misc_integrity_result_do(chip_id, line, result, &check_pass);
        sal_fprintf(rslt_fp, "%s", result);

        sal_memset(line, 0, MAX_PER_LINE);
        sal_memset(result, 0, MAX_PER_LINE);
    }

    if (check_pass)
    {
        CTC_DKIT_PRINT("integrity check passed!\n");
        ret = DRV_E_NONE;
    }
    else
    {
        ret = DRV_E_RESERVD_VALUE_ERROR;
    }
error1:
    /*close file*/
    if (NULL != gold_fp)
    {
        sal_fclose(gold_fp);
        gold_fp = NULL;
    }
    if (NULL != rslt_fp)
    {
        sal_fclose(rslt_fp);
        rslt_fp = NULL;
    }
    if (line)
    {
        mem_free(line);
    }
    if (result)
    {
        mem_free(result);
    }
    return ret;
}

#define __get_chip_info___
int32
ctc_usw_dkit_misc_chip_info(uint8 lchip, sal_file_t p_wf)
{
    uint32      cmd = 0;
    DevId_m    read_device_id;
    EcidRegMem_m ecid_reg;
    uint32      value = 0;
    uint32      get_device_id = 0;
    ctc_dkit_device_id_type_t dev_id;
    uint32      version_id = 0;
    char        chip_name[CTC_DKIT_CHIP_NAME_LEN] = {0};
    uint8       svb  = 0;
    CTC_DKIT_LCHIP_CHECK(lchip);
    sal_memset(&read_device_id, 0, sizeof(DevId_m));
    sal_memset(&ecid_reg, 0, sizeof(EcidRegMem_m));
    cmd = DRV_IOR(DevId_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &read_device_id);

    value = GetDevId(V,deviceId_f,&read_device_id);

    version_id = value & 0x0F;
    get_device_id  = (value >> 4) & 0x0F;
    sal_strcpy(chip_name, (get_device_id == 0x07) ? "CTC7148": "Not Support Chip");
    dev_id = (get_device_id == 0x07) ? CTC_DKIT_DEVICE_ID_DUET2_CTC7148 : CTC_DKIT_DEVICE_ID_INVALID;

    cmd = DRV_IOR(EcidRegMem_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 3, cmd, &ecid_reg);
    value = GetEcidRegMem(V, data_f, &ecid_reg);
    svb = (value >> 2) & 0xF;

    CTC_DKITS_PRINT_FILE(p_wf, "Chip name: %s, Device Id: %d, Version Id: %d Svb: %d\n",
                               chip_name, dev_id, version_id, svb);


    sal_memset(chip_name, 0, CTC_DKIT_CHIP_NAME_LEN);
    ctc_usw_dkit_get_chip_name(lchip, chip_name);
    CTC_DKITS_PRINT_FILE(p_wf, "Dkits %s Released at %s Chip Series: %s\n"
            , CTC_DKITS_VERSION_STR, CTC_DKITS_RELEASE_DATE, chip_name);
    CTC_DKITS_PRINT_FILE(p_wf, "-------------------------------------------------------------\n");

    return CLI_SUCCESS;
}



